package com.mulanweb.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.StrKit;
import com.mulanweb.validator.ValidateStatus;
import com.mulanweb.validator.ValidateUtils;
import com.mulanweb.validator.annotation.ValidateFile;
import com.mulanweb.validator.annotation.ValidateForm;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;

/**
 * 验证拦截器
 * Created by hcy on 2016/4/9.
 */
public class ValidatorInterceptor implements Interceptor {

    /**
     * 拦截器配置信息
     */
    private static class ValidateConfig {
        /**
         * 配置文件
         */
        public final String file;
        /**
         * from名称
         */
        public final String form;

        public ValidateConfig(String file, String form) {
            this.file = file;
            this.form = form;
        }
    }

    private static Map<String, ValidateConfig> validateConfigCache = new HashMap<>();

    /**
     * 根据Invocation得到拦截器配置信息，如果该请求无需验证，返回null
     *
     * @param inv Invocation实例
     * @return 配置信息
     */
    private ValidateConfig getValidateConfig(Invocation inv) {

        if (validateConfigCache.containsKey(inv.getActionKey())) {
            return validateConfigCache.get(inv.getActionKey());
        }

        ValidateForm vForm = getForm(inv);
        if (null == vForm) {
            validateConfigCache.put(inv.getActionKey(), null);
            return null;
        }
        ValidateFile vFile = getFile(inv);

        String form = StrKit.notBlank(vForm.value()) ? vForm.value() : inv.getMethodName();
        String file = null != vFile ? vForm.value() : null;

        if (StrKit.isBlank(file)) {
            file = inv.getController().getClass().getName().replace(".", "/") + ".xml";
        }
        ValidateConfig vc = new ValidateConfig(file, form);
        validateConfigCache.put(inv.getActionKey(), vc);
        return vc;
    }

    /**
     * 获取请求参数
     *
     * @param inv
     * @return
     */
    private Map<String, String> getRequestParaMap(Invocation inv) {
        Map<String, String> newParaMap = new HashMap<String, String>();
        inv.getController().getParaMap().forEach((name, values) -> newParaMap.put(name, values[0]));
        return newParaMap;
    }

    /**
     * 得到请求中的配置文件
     *
     * @param inv
     * @return
     */
    private ValidateFile getFile(Invocation inv) {
        for (Annotation annotation : inv.getMethod().getDeclaredAnnotations()) {
            if (annotation instanceof ValidateFile) {
                return (ValidateFile) annotation;
            }
        }
        for (Annotation annotation : inv.getController().getClass().getDeclaredAnnotations()) {
            if (annotation instanceof ValidateFile) {
                return (ValidateFile) annotation;
            }
        }
        return null;
    }

    /**
     * 得到请求配置表单
     *
     * @param inv
     * @return
     */
    private ValidateForm getForm(Invocation inv) {
        for (Annotation annotation : inv.getMethod().getDeclaredAnnotations()) {
            if (annotation instanceof ValidateForm) {
                return (ValidateForm) annotation;
            }
        }
        return null;
    }

//    private Log log = Log.getLog(ValidatorInterceptor.class);

    @Override
    public void intercept(Invocation inv) {

        ValidateConfig vc = getValidateConfig(inv);
        if (null == vc) {
            inv.invoke();
        } else {
            Map<String, String> paraMap = getRequestParaMap(inv);
            ValidateStatus vs = ValidateUtils.validate(vc.file, vc.form, paraMap);
            if (vs.equals(ValidateStatus.SUCCESS)) {
                inv.invoke();
            } else {
                inv.getController().renderJson(vs);
            }
        }

    }


}
